package com.stockz.indicator.ord;

import com.stockz.core.model.Bar;
import com.stockz.core.util.BarUtil;
import com.stockz.core.util.BarUtil.BarValueType;

public class OrdSwing implements Comparable<OrdSwing>{

	public static enum OrdSwingValue{
		VOLUME,
		AVERAGE_DAILY_VOLUME,
		PERCENTAGE_CHANGE,
		VOLUME_PER_PERCENTAGE_CHANGE,
		AVERAGE_DAILY_VOLUME_PER_PERCENTAGE_CHANGE;
	};
	
	public static enum OrdSwingDirection{
		UP,
		DOWN,
		UNCHANGED,
		UNDEFINED;
	};
	
	public static enum OrdSwingType{
		BULLISH,
		BEARISH,
		NEUTRAL,
		UNDEFINED;
	};
	
	private Bar start;
	private Bar end;
	
	private double volume = 0;
	private double span = 0;
	
	private OrdSwingType type;
	
	@Override
	public int compareTo(OrdSwing o) {
		if(o == null
				|| o.getEnd() == null
				|| getEnd() == null){
			return 0;
		}
		return getEnd().compareTo(o.getEnd());
	}
	
	public double getValue(OrdSwingValue value){
		switch(value){
		case VOLUME : return getVolume();
		case AVERAGE_DAILY_VOLUME : return getAverageDailyVolume();
		case PERCENTAGE_CHANGE : return getPercentageChange();
		case VOLUME_PER_PERCENTAGE_CHANGE : return getVolumePerPercentageChange();
		case AVERAGE_DAILY_VOLUME_PER_PERCENTAGE_CHANGE : return getAverageDailyVolumePerPercentageChange();
		default : return 0;
		}
	}
	
	
	public double getAverageDailyVolume(){
		if(getSpan() == 0){
			return 0;
		}else{
			return getVolume()/getSpan();			
		}
	}
	
	public double getPercentageChange(){
		if(getStart() != null && getEnd() != null && getDirection() != null){
			switch (getDirection()){
			case DOWN : 				
				return (BarUtil.getValue(getStart(),BarValueType.AVGPRICE) - BarUtil.getValue(getEnd(),BarValueType.AVGPRICE))*100/BarUtil.getValue(getEnd(),BarValueType.AVGPRICE);
			case UP : 
				return (BarUtil.getValue(getEnd(),BarValueType.AVGPRICE) - BarUtil.getValue(getStart(),BarValueType.AVGPRICE))*100/BarUtil.getValue(getStart(),BarValueType.AVGPRICE);
			case UNCHANGED : 
				return 0;
			case UNDEFINED : 
				return 0;
			default : return 0;
			}
		}else{
			return 0;
		}
	}
	
	
	public double getVolumePerPercentageChange(){
		double ppc = getPercentageChange();
		if(ppc == 0){
			return 0;
		}else{
			return getVolume()/ppc;
		}
	}

	public double getAverageDailyVolumePerPercentageChange(){
		double ppc = getPercentageChange();
		if(ppc == 0){
			return 0;
		}else{
			return getAverageDailyVolume()/ppc;
		}
	}
	
	public Bar getStart() {
		return start;
	}

	public void setStart(Bar start) {
		this.start = start;
	}

	public Bar getEnd() {
		return end;
	}

	public void setEnd(Bar end) {
		this.end = end;
	}

	public double getVolume() {
		return volume;
	}

	public void setVolume(double volume) {
		this.volume = volume;
	}

	public double getSpan() {
		return span;
	}

	public void setSpan(double span) {
		this.span = span;
	}

	public OrdSwingDirection getDirection() {
		if(getEnd() != null 
				&& getStart() != null){
			if(BarUtil.getValue(getStart(),BarValueType.AVGPRICE) > BarUtil.getValue(getEnd(),BarValueType.AVGPRICE)){
				return OrdSwingDirection.DOWN;
			}else if(BarUtil.getValue(getStart(),BarValueType.AVGPRICE) < BarUtil.getValue(getEnd(),BarValueType.AVGPRICE)){
				return OrdSwingDirection.UP;
			}else{
				return OrdSwingDirection.UNCHANGED;
			}
		}
		return OrdSwingDirection.UNDEFINED;
	}

	public OrdSwingType getType() {
		return type;
	}

	public void setType(OrdSwingType type) {
		this.type = type;
	}
	
}
